package cn.yto.print.utils;

import cn.yto.print.enums.PluginRegistryEnum;
import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.WinReg;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.awt.*;
import java.io.File;
import java.util.List;

public class PluginInstalledUtil {

    private static final Logger logger = LogManager.getLogger(PluginInstalledUtil.class);

    public static final String HKU_PREFIX = "SID\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
    public static final String HKLM_PREFIX_32 = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
    public static final String HKLM_PREFIX_64 = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";

    /**
     * 启动打印组件
     */
    public static void startUpPlugin(String path) {
        String workDirPath = path.substring(0, path.lastIndexOf("\\"));
        File workDirectory = new File(workDirPath);
        // 通过 ProcessBuilder 构造启动命令
        ProcessBuilder processBuilder = new ProcessBuilder(path);
        processBuilder.directory(workDirectory);
        processBuilder.redirectErrorStream(true);
        try {
            processBuilder.start();
        } catch (Exception e) {
            logger.error("启动打印组件异常", e);
        }
    }

    /**
     * 启动打印组件
     */
    public static Process startUpProcess() {
        String exeName = "打印助手.exe";
        File exeFile = new File(System.getProperty("user.dir"), exeName);
        String exeFilePath = exeFile.getAbsolutePath();
        File workDirectory = new File(exeFilePath.substring(0, exeFilePath.lastIndexOf("\\")));
        ProcessBuilder processBuilder = new ProcessBuilder(exeFilePath);
        processBuilder.directory(workDirectory);
        processBuilder.redirectErrorStream(true);
        try {
            return processBuilder.start();
        } catch (Exception e) {
            logger.error("启动打印组件异常", e);
            return null; // 保证异常时返回空对象
        }
    }

    /**
     * 启动打印组件
     */
    public static void startUpDeskPlugin(String path) {
        try {
            File targetFile = new File(path);
            Desktop.getDesktop().open(targetFile);
        } catch (Exception e) {
            logger.error("启动外部应用程序 {} 发生异常", path, e);
        }
    }

    /**
     * 检测插件是否安装，如果安装返回本地安装路径
     */
    public static String getPluginInstallPath(PluginRegistryEnum registryKeyEnum) {
        String initialPathKey = HKLM_PREFIX_32 + registryKeyEnum.getRegistryPath();
        String installPath = getRegPath(WinReg.HKEY_LOCAL_MACHINE, initialPathKey, registryKeyEnum.getStartUpPathKey());
        if (StringUtils.isEmpty(installPath)) {
            if (PluginRegistryEnum.CN.equals(registryKeyEnum)) {
                installPath = getCnPluginPath(registryKeyEnum, initialPathKey);
            }
        }
        if (StringUtils.isEmpty(installPath)) {
            if (PluginRegistryEnum.AKC.equals(registryKeyEnum)) {
                installPath = getAkcPluginPath(registryKeyEnum, installPath);
            }
        }
        if (StringUtils.isEmpty(installPath)) {
            String userSid = getSid(); // 获取当前 SID
            String userPathKey = HKU_PREFIX.replace("SID", userSid) + registryKeyEnum.getRegistryPath();
            installPath = getRegPath(WinReg.HKEY_USERS, userPathKey, registryKeyEnum.getStartUpPathKey());
        }
        if (!StringUtils.isEmpty(installPath)) {
            installPath = adjustPathIfNeeded(installPath, registryKeyEnum);
        }
        return installPath;
    }

    /**
     * 调整插件路径格式
     */
    private static String adjustPathIfNeeded(String path, PluginRegistryEnum registryKeyEnum) {
        String adjustedPath = path;
        if (PluginRegistryEnum.DY.equals(registryKeyEnum) ||
                PluginRegistryEnum.KS.equals(registryKeyEnum) ||
                PluginRegistryEnum.AKC.equals(registryKeyEnum)) {
            adjustedPath += "\\" + registryKeyEnum.getProcesses();
        }
        if (!adjustedPath.contains(".exe")) {
            adjustedPath = adjustedPath.substring(0, adjustedPath.lastIndexOf("\\")) +
                    "\\" + registryKeyEnum.getProcesses();
        }
        adjustedPath = adjustedPath.replace(",0", "");
        if (adjustedPath.startsWith("\"") && adjustedPath.endsWith("\"")) {
            adjustedPath = adjustedPath.substring(1, adjustedPath.length() - 1);
        }
        return adjustedPath;
    }

    /**
     * 获取当前Windows用户SID
     */
    private static String getSid() {
        String keyPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList";
        List<String> sids = RegistryUtil.getSidsWithPrefix(keyPath);
        return !sids.isEmpty() ? sids.get(0) : "";
    }

    /**
     * 从注册表获取值
     */
    private static String getRegPath(WinReg.HKEY root, String key, String valueName) {
        try {
            return Advapi32Util.registryGetStringValue(root, key, valueName);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 爱库存打印组件注册表
     */
    private static String getAkcPluginPath(PluginRegistryEnum registryKeyEnum, String path) {
        String[] subkeys = Advapi32Util.registryGetKeys(WinReg.HKEY_LOCAL_MACHINE, HKLM_PREFIX_32);
        for (String subkey : subkeys) {
            if (subkey.startsWith(PluginRegistryEnum.AKC.getRegistryPath())) {
                path = getRegPath(WinReg.HKEY_LOCAL_MACHINE, HKLM_PREFIX_32 + subkey, registryKeyEnum.getStartUpPathKey());
            }
        }
        if (StringUtils.isEmpty(path)) {
            subkeys = Advapi32Util.registryGetKeys(WinReg.HKEY_LOCAL_MACHINE, HKLM_PREFIX_64);
            for (String subkey : subkeys) {
                if (subkey.startsWith(PluginRegistryEnum.AKC.getRegistryPath())) {
                    path = getRegPath(WinReg.HKEY_LOCAL_MACHINE, HKLM_PREFIX_64 + subkey, registryKeyEnum.getStartUpPathKey());
                }
            }
        }
        return path;
    }

    /**
     * 获取菜鸟打印组件注册表
     */
    private static String getCnPluginPath(PluginRegistryEnum registryKeyEnum, String pathKey) {
        String[] altPaths = {
                pathKey.replace("菜鸟打印组件", "CAINIAO打印组件"),
                pathKey.replace("菜鸟打印组件", "{CAINIAO打印组件}}_is1")
        };
        for (String altPath : altPaths) {
            String installPath = getRegPath(WinReg.HKEY_LOCAL_MACHINE, altPath, registryKeyEnum.getStartUpPathKey());
            if (!installPath.isEmpty()) {
                return installPath;
            }
        }
        return null;
    }

}